package com.lzj.gen.jetbrains;

import com.alibaba.fastjson.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * Created by lzj on 2023/11/24
 */
public class CodeUtil {

    private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();

    public static String genActiveCode(String certFile, String keyFile, String licenseJsonStr)
            throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
            IOException, SignatureException, CertificateException {

        byte[] certBytes = PemUtil.readPem(certFile);
        String certFullStr = PemUtil.readPemFullStr(certFile);
        String certStr = BASE64_ENCODER.encodeToString(certBytes);
        byte[] privateKeyBytes = PemUtil.readPem(keyFile);

        //PKCS#8
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory= KeyFactory.getInstance("RSA");
        PrivateKey priKey= keyFactory.generatePrivate(pkcs8KeySpec);

        JSONObject licenseObj = JSONObject.parseObject(licenseJsonStr);
        String licenseId = licenseObj.getString("licenseId");
        byte[] licenseBytes = licenseJsonStr.getBytes("utf-8");

        Signature privateSignature = Signature.getInstance("SHA1withRSA");
        privateSignature.initSign(priKey);
        privateSignature.update(licenseBytes);
        byte[] signature = privateSignature.sign();

        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        X509Certificate x509Certificate = (X509Certificate) certFactory.generateCertificate(
                new ByteArrayInputStream(certFullStr.getBytes()));
        Signature publicSignature = Signature.getInstance("SHA1withRSA");
        publicSignature.initVerify(x509Certificate.getPublicKey());
        publicSignature.update(licenseBytes);
        if (!publicSignature.verify(signature)) {
            throw new RuntimeException("signature verify error");
        }
        return licenseId + "-" + BASE64_ENCODER.encodeToString(licenseBytes) +
                "-" + BASE64_ENCODER.encodeToString(signature) + "-" + certStr;
    }
}
